//
// Created by yunlang on 2021/12/20.
//
#include "menu.h"
using namespace std;
void readFile()
{
    string filename;
    cout << "Input the filename" << endl;
    cin >> filename;
    string s = "cat /home/yunlang/work/CLionProjects/FileArchiver/build/" + filename;
    system(s.c_str());
    getchar();
    getchar();
    system("clear");
    menu();
}
void menu()
{
    string command;
    const string EncodeCmd = "e";
    const string DecodeCmd = "d";
    const string Quit = "q";
    const string Generate = "g";
    const string Read = "r";
    cout << "Input your choice:(\"e\"for encode, \"d\"for decode,\"g\"for generate text,\"r\"for read,\"q\"for quit): " << endl;
    cin >> command;
    if (command == EncodeCmd) {
        encodeFile();
    } else if (command == DecodeCmd) {
        decodeFile();
    } else if (command == Generate) {
        generateText();
    }else if(command == Read)
    {
        readFile();
    } else if (command == Quit) {
        exit(0);
    }else {
        cout << endl;
        cout << "Wrong Command!" << endl;
        getchar();
        getchar();
        system("clear");
    }
    menu();
}

void generateText()
{
    string filename;
    cout << "Input the filename" << endl;
    cin >> filename;
    string s = "/home/yunlang/work/CLionProjects/FileArchiver/build/" + filename;
    FILE *fp = fopen(s.c_str(),"w");
    time_t t;
    srand((unsigned)time(&t));
    int i;
    for(int i = 0; i < 10000; i++)
    {
        fprintf(fp,"%c",97+(rand()%26));
    }
    cout << "Success!" << endl;
    getchar();
    getchar();
//    getchar();
    system("clear"); //if in Linux, please use clear and if in Windows please use cls
    menu();
}
void encodeFile() {
    string Filename, encodedFilename;
    cout << "Please input filename:" << endl;
    cin >> Filename;

    cout << "Please input encoded filename(with extension name \".hfmc\"):" << endl;
    cin >> encodedFilename;
    if (encodedFilename.length() < 6 || encodedFilename.substr(encodedFilename.length() - 5) != ".hfmc") {
        ;
    }

    File* filePtr = FileIO::readFromFile(Filename);
    HuffmanCompression encoder;
    unordered_map<unsigned char, unsigned int> weightMap;
    unsigned char *encodedDataPtr = nullptr;
    unsigned int encodedDataBitSize;
    encoder.getEncodedData(filePtr -> getFileData(), filePtr-> getDataBitSize(),
                           weightMap, encodedDataPtr, encodedDataBitSize);

    cout << "Encoded data bit size: " << encodedDataBitSize << endl;
    unsigned int encodedDataSize = encodedDataBitSize / 8 + (encodedDataBitSize % 8 == 0 ? 0 : 1);
    cout << "EncodedDataSize: " << encodedDataSize << " Bytes" << endl;

    FileIO::writeToZip(filePtr->getFileType(),encodedFilename, weightMap,
                       encodedDataPtr, encodedDataSize, encodedDataBitSize);

    delete [] encodedDataPtr;
    delete filePtr;
    cout << "Success!" << endl;
    getchar();
    getchar();
//    system("pause");
    system("clear"); //if in Linux, please use clear and if in Windows please use cls
    menu();
}

void decodeFile() {
    string Filename, encodedFilename;

    cout << "Please input encoded filename(with extension name \".hfmc\"):" << endl;
    cin >> encodedFilename;
    if (encodedFilename.length() < 6 || encodedFilename.substr(encodedFilename.length() - 5) != ".hfmc") {
        ;
    }

    cout << "Please input filename" << endl;
    cin >> Filename;
    if (Filename.length() < 5) {
        ;
    }

    FileEncode* fileEncodePtr = FileIO::readFromZip(encodedFilename);
    HuffmanCompression decoder;

    unsigned char *decodedDataPtr = nullptr;
    unsigned int decodedDataSize;

    decoder.getDecodeData(fileEncodePtr -> getData(),
                          fileEncodePtr -> getDataBitSize(),
                          fileEncodePtr -> getWeightMapArr(),
                          decodedDataPtr, decodedDataSize);
    cout << "Decoded data size: " << decodedDataSize << " Bytes" << endl;

    FileIO::writeToFile(Filename,
                        fileEncodePtr->getFileInfo(),
                        decodedDataPtr,
                        decodedDataSize);

    delete [] decodedDataPtr;
    delete fileEncodePtr;
    cout << "Success!" << endl;
    getchar();
    getchar();
//    system("pause");
    system("clear"); //if in Linux, please use clear and if in Windows please use cls
    menu();
}